// 版权归Go作者所有。版权所有。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

package xcoff

// 文件头。
type FileHeader32 struct {
	Fmagic   uint16 // 目标机器
	Fnscns   uint16 // 节数
	Ftimedat int32  // 文件创建时间和日期
	Fsymptr  uint32 // 符号表的字节偏移量start 
	Fnsyms   int32  // 符号表中的条目数
	Fopthdr  uint16 // 可选头中的字节数
	Fflags   uint16 // 标志
}

type FileHeader64 struct {
	Fmagic   uint16 // 目标机器
	Fnscns   uint16 // 节数
	Ftimedat int32  // 文件创建时间和日期
	Fsymptr  uint64 // 到符号表的字节偏移量start 
	Fopthdr  uint16 // 可选头中的字节数
	Fflags   uint16 // 标志
	Fnsyms   int32  // 符号表中的条目数
}

const (
	FILHSZ_32 = 20
	FILHSZ_64 = 24
)
const (
	U802TOCMAGIC = 0737 // AIX 32位XCOFF 
)

// 描述对象文件类型的标志。
const (
	F_RELFLG    = 0x0001
	F_EXEC      = 0x0002
	F_LNNO      = 0x0004
	F_FDPR_PROF = 0x0010
	F_FDPR_OPTI = 0x0020
	F_DSA       = 0x0040
	F_VARPG     = 0x0100
	F_DYNLOAD   = 0x1000
	F_SHROBJ    = 0x2000
	F_LOADONLY  = 0x4000
)

// 节头。
type SectionHeader32 struct {
	Sname    [8]byte // 节名
	Spaddr   uint32  // 物理地址
	Svaddr   uint32  // 虚拟地址
	Ssize    uint32  // 节大小
	Sscnptr  uint32  // 节的文件到原始数据的偏移量
	Srelptr  uint32  // 节的文件到重定位项的偏移量
	Slnnoptr uint32  // 节的文件到行号项的偏移量
	Snreloc  uint16  // 重定位条目的数量
	Snlnno   uint16  // 行号条目的数量
	Sflags   uint32  // 定义节类型的标志
}

type SectionHeader64 struct {
	Sname    [8]byte // 节名
	Spaddr   uint64  // 物理地址
	Svaddr   uint64  // 虚拟地址
	Ssize    uint64  // 节大小
	Sscnptr  uint64  // 文件中的偏移量到的原始数据节
	Srelptr  uint64  // 节
	Slnnoptr uint64  // 节
	Snreloc  uint32  // 节
	Snlnno   uint32  // 重新定位条目的数量
	Sflags   uint32  // 定义节类型
	Spad     uint32  // 的标志需要为72字节long 
}

// 定义节类型的标志。
const (
	STYP_DWARF  = 0x0010
	STYP_TEXT   = 0x0020
	STYP_DATA   = 0x0040
	STYP_BSS    = 0x0080
	STYP_EXCEPT = 0x0100
	STYP_INFO   = 0x0200
	STYP_TDATA  = 0x0400
	STYP_TBSS   = 0x0800
	STYP_LOADER = 0x1000
	STYP_DEBUG  = 0x2000
	STYP_TYPCHK = 0x4000
	STYP_OVRFLO = 0x8000
)
const (
	SSUBTYP_DWINFO  = 0x10000 // 矮人信息部分
	SSUBTYP_DWLINE  = 0x20000 // 矮人行号部分
	SSUBTYP_DWPBNMS = 0x30000 // 矮人公共名称部分
	SSUBTYP_DWPBTYP = 0x40000 // 矮人公共类型部分
	SSUBTYP_DWARNGE = 0x50000 // 矮人aranges部分
	SSUBTYP_DWABREV = 0x60000 // 矮人缩写部分
	SSUBTYP_DWSTR   = 0x70000 // 矮人字符串部分
	SSUBTYP_DWRNGES = 0x80000 // 矮人范围部分
	SSUBTYP_DWLOC   = 0x90000 // 矮人位置列表部分
	SSUBTYP_DWFRAME = 0xA0000 // 矮人框架部分
	SSUBTYP_DWMAC   = 0xB0000 // 矮人宏部分
)

// 符号表项。
type SymEnt32 struct {
	Nname   [8]byte // 符号名称
	Nvalue  uint32  // 符号值
	Nscnum  int16   // 符号段号
	Ntype   uint16  // 基本和派生类型规范
	Nsclass int8    // 符号存储类
	Nnumaux int8    // 辅助项数
}

type SymEnt64 struct {
	Nvalue  uint64 // 符号值
	Noffset uint32 // 中名称的偏移量字符串表或.debug节
	Nscnum  int16  // 符号节号
	Ntype   uint16 // 基本和派生类型规范
	Nsclass int8   // 符号存储类
	Nnumaux int8   // 辅助项数
}

const SYMESZ = 18

const (
	// Nscnum 
	N_DEBUG = -2
	N_ABS   = -1
	N_UNDEF = 0

	// Ntype 
	SYM_V_INTERNAL  = 0x1000
	SYM_V_HIDDEN    = 0x2000
	SYM_V_PROTECTED = 0x3000
	SYM_V_EXPORTED  = 0x4000
	SYM_TYPE_FUNC   = 0x0020 // 是函数
)

// 存储类。
const (
	C_NULL    = 0   // 标记为删除的符号表项
	C_EXT     = 2   // 外部符号
	C_STAT    = 3   // 静态符号
	C_BLOCK   = 100 // 内部块的开始或结束
	C_FCN     = 101 // 函数的开始或结束
	C_FILE    = 103 // 源文件名和编译器信息
	C_HIDEXT  = 107 // 未命名的外部符号
	C_BINCL   = 108 // 包含文件的开头
	C_EINCL   = 109 // 包含文件的结尾
	C_WEAKEXT = 111 // 弱外部符号
	C_DWARF   = 112 // 矮化符号
	C_GSYM    = 128 // 全局变量
	C_LSYM    = 129 // 堆栈上分配的自动变量
	C_PSYM    = 130 // 堆栈上分配的子例程参数
	C_RSYM    = 131 // 寄存器变量
	C_RPSYM   = 132 // 存储在寄存器
	C_STSYM   = 133 // 静态分配符号
	C_BCOMM   = 135 // 公共块的开始
	C_ECOML   = 136 // 公共块的本地成员
	C_ECOMM   = 137 // 公共块的结束
	C_DECL    = 140 // 对象的声明
	C_ENTRY   = 141 // 备用项
	C_FUN     = 142 // 函数或过程
	C_BSTAT   = 143 // 静态块开始
	C_ESTAT   = 144 // 静态块结束
	C_GTLS    = 145 // 全局线程局部变量
	C_STTLS   = 146 // 静态线程局部变量
)

// 文件辅助项
type AuxFile64 struct {
	Xfname   [8]byte // 字符串内的名称或偏移量表
	Xftype   uint8   // 源文件字符串类型
	Xauxtype uint8   // 辅助项类型
}

// 函数辅助项
type AuxFcn32 struct {
	Xexptr   uint32 // 文件到异常表项的偏移量
	Xfsize   uint32 // 函数大小（字节）
	Xlnnoptr uint32 // 指向行号
	Xendndx  uint32 // 下一条目的符号表索引
	Xpad     uint16 // 未使用的
}
type AuxFcn64 struct {
	Xlnnoptr uint64 // 指向行号
	Xfsize   uint32 // 函数大小（字节）
	Xendndx  uint32 // 下一条目的符号表索引
	Xpad     uint8  // 未使用的
	Xauxtype uint8  // 辅助类型条目
}

type AuxSect64 struct {
	Xscnlen  uint64 // 段长
	Xnreloc  uint64 // Num RLDs 
	pad      uint8
	Xauxtype uint8 // 辅助条目类型
}

// /csect辅助条目。
type AuxCSect32 struct {
	Xscnlen   int32  // 长度或符号表索引
	Xparmhash uint32 // 参数类型检查字符串的偏移量
	Xsnhash   uint16 // .typchk节号
	Xsmtyp    uint8  // 符号对齐和类型
	Xsmclas   uint8  // 存储映射类
	Xstab     uint32 // 保留
	Xsnstab   uint16 // 保留
}

type AuxCSect64 struct {
	Xscnlenlo uint32 // 数据的下4个字节长度或符号表索引
	Xparmhash uint32 // 参数类型检查字符串的偏移量
	Xsnhash   uint16 // .typchk节号
	Xsmtyp    uint8  // 符号对齐和类型
	Xsmclas   uint8  // 存储映射类
	Xscnlenhi int32  // 长度或符号表索引的上4字节
	Xpad      uint8  // 未使用的
	Xauxtype  uint8  // 类型辅助条目的编号
}

// 辅助类型
const (
	_AUX_EXCEPT = 255
	_AUX_FCN    = 254
	_AUX_SYM    = 253
	_AUX_FILE   = 252
	_AUX_CSECT  = 251
	_AUX_SECT   = 250
)

// 符号类型字段。
const (
	XTY_ER = 0 // 外部引用
	XTY_SD = 1 // 节定义
	XTY_LD = 2 // 标签定义
	XTY_CM = 3 // 通用csect定义
)

// 为文件辅助定义定义：x_文件的x_ftype字段
const (
	XFT_FN = 0   // 源文件名
	XFT_CT = 1   // 编译时间戳
	XFT_CV = 2   // 编译器版本号
	XFT_CD = 128 // 编译器定义信息
)

// 存储映射类。
const (
	XMC_PR     = 0  // 程序代码
	XMC_RO     = 1  // 只读常量
	XMC_DB     = 2  // 调试字典表
	XMC_TC     = 3  // TOC条目
	XMC_UA     = 4  // 未分类
	XMC_RW     = 5  // 读/写数据
	XMC_GL     = 6  // 全局链接
	XMC_XO     = 7  // 扩展操作
	XMC_SV     = 8  // 32位主管调用描述符
	XMC_BS     = 9  // BSS类
	XMC_DS     = 10 // 函数描述符
	XMC_UC     = 11 // 未命名FORTRAN通用
	XMC_TC0    = 15 // TOC锚
	XMC_TD     = 16 // TOC中的标量数据项
	XMC_SV64   = 17 // 64位主管调用描述符
	XMC_SV3264 = 18 // 32位和64位的主管调用描述符
	XMC_TL     = 20 // 读/写线程本地数据
	XMC_UL     = 21 // 读/写线程本地数据（.tbss）
	XMC_TE     = 22 // TOC条目
)

// 加载头。
type LoaderHeader32 struct {
	Lversion int32  // 加载程序段版本号
	Lnsyms   int32  // 符号表项数
	Lnreloc  int32  // 重定位表项数
	Listlen  uint32 // 导入文件ID字符串表长度
	Lnimpid  int32  // 导入文件ID数
	Limpoff  uint32 // 导入文件ID开始偏移量
	Lstlen   uint32 // 字符串表长度
	Lstoff   uint32 // 字符串表起始偏移量
}

type LoaderHeader64 struct {
	Lversion int32  // 加载程序段版本号
	Lnsyms   int32  // 符号表条目数
	Lnreloc  int32  // 重定位表条目数
	Listlen  uint32 // 导入文件ID字符串表长度
	Lnimpid  int32  // 导入文件ID数
	Lstlen   uint32 // 字符串表的长度
	Limpoff  uint64 // 导入文件ID的开始偏移量
	Lstoff   uint64 // 字符串表的开始偏移量
	Lsymoff  uint64 // 符号表的开始偏移量
	Lrldoff  uint64 // 重定位项的开始偏移量
}

const (
	LDHDRSZ_32 = 32
	LDHDRSZ_64 = 56
)

// 加载程序符号。
type LoaderSymbol32 struct {
	Lname   [8]byte // 字符串表中的符号名称或字节偏移量
	Lvalue  uint32  // 地址字段
	Lscnum  int16   // 包含符号的节号
	Lsmtype int8    // 符号类型、导出、导入标志
	Lsmclas int8    // 符号存储类
	Lifile  int32   // 导入文件ID；导入文件ID顺序
	Lparm   uint32  // 参数类型检查字段
}

type LoaderSymbol64 struct {
	Lvalue  uint64 // 地址字段
	Loffset uint32 // 字节偏移量到符号名
	Lscnum  int16  // 包含符号的节号
	Lsmtype int8   // 符号类型，导出，导入标志
	Lsmclas int8   // 符号存储类
	Lifile  int32  // 导入文件ID；导入文件ID的序号
	Lparm   uint32 // 参数类型检查字段
}

type Reloc32 struct {
	Rvaddr  uint32 // （虚拟）引用地址
	Rsymndx uint32 // 索引到符号表
	Rsize   uint8  // 符号和重新链接位len 
	Rtype   uint8  // Toc重定位类型
}

type Reloc64 struct {
	Rvaddr  uint64 // （虚拟）引用地址
	Rsymndx uint32 // 符号表中的索引
	Rsize   uint8  // 符号和重新定位位len 
	Rtype   uint8  // Toc重定位类型
}

const (
	R_POS = 0x00 // A（sym）正重定位
	R_NEG = 0x01 // -A（sym）负重定位
	R_TOC = 0x03 // A（sym Toc）相对于TOC 
	R_TRL = 0x12 // A（sym TOC）TOC相对间接负荷。

	R_TRLA = 0x13 // A（sym TOC）TOC Rel加载地址。可修改指令
	R_GL   = 0x05 // A（sym外部TOC）全局链接
	R_TCL  = 0x06 // A（sym本地TOC）本地对象TOC地址
	R_RL   = 0x0C // A（sym）Pos间接加载。可修改指令
	R_RLA  = 0x0D // A（sym）Pos加载地址。可修改指令
	R_REF  = 0x0F // AL0（sym）非重定位引用无垃圾收集
	R_BA   = 0x08 // A（sym）绝对分支。无法修改指令
	R_RBA  = 0x18 // A（sym）绝对分支。可修改指令
	R_BR   = 0x0A // A（sym-*）分支与自身相关。不可修改的
	R_RBR  = 0x1A // A（sym-*）分支与自身相关。可修改的指令

	R_TLS    = 0x20 // 对TLS符号
	R_TLS_IE = 0x21 // 对TLS符号
	R_TLS_LD = 0x22 // 对TLS符号
	R_TLS_LE = 0x23 // 对TLS符号
	R_TLSM   = 0x24 // 对TLS符号
	R_TLSML  = 0x25 // 对本地（自有）模块

	R_TOCU = 0x30 // 相对于TOC-高位
	R_TOCL = 0x31 // 相对于TOC-低位
)
